home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / CC_C / 0151.ZIP / TF.C < prev    next >
C/C++ Source or Header  |  1985-10-25  |  16KB  |  638 lines

  1. /********************************************************
  2. *                            *
  3. *           T E X T  F O R M             *
  4. *           Text file formatter for MSDOS        *
  5. *                            *
  6. *          T. Jennings 24 Oct 85            *
  7. *            created 14 Nov. 82        *
  8. *                            *
  9. *********************************************************
  10.  
  11.     TEXTFORM prints and/or formats edited text, using WordStar
  12. compatible dot commands, for use on non-WordStar systems. See 
  13. TEXTFORM.DOC for details. */
  14.  
  15. #include <ascii.h>
  16.  
  17. char *next_arg();
  18. char *skip_delim();
  19. char *strip_path();
  20.  
  21. #define FALSE 0
  22. #define TRUE 1
  23. #define ERROR -1
  24. #define BOLD 2                /* ^B bold on/off, */
  25. #define UNDER 19            /* ^S understrike, */
  26. #define DOUBLE 4            /* ^D double strike, */
  27. #define STRIKE 24            /* ^X strikeout */
  28.  
  29. int line_count;                /* total lines, */
  30. int this_line;                /* current line #/page */
  31. int this_page;                /* current page */
  32. int abs_page;                /* physical page */
  33. int this_col;
  34. int pagelen;                /* current max page length */
  35. int lmargin,rmargin;            /* current left and right margins */
  36. int top_margin;                /* lines from top of page */
  37. int bot_margin;                /* lines at bottom of page */
  38. int num_pages;                /* true if do page numbers */
  39.  
  40. int csource;                /* true if paging C sources, */
  41. int brackets;                /* bracket nesting level */
  42. int newpage;                /* time for a new page, */
  43. int lineno;                /* true if doing line numbers */
  44. int title;                /* true if top of page titles */
  45. int first_page;                /* first page to print, */
  46.  
  47. int infile;                /* main text file */
  48. int auxfile;                /* include file */
  49. int outfile;
  50. char auxname[80];
  51. char inname[80];            /* where we save ASCII filenames */
  52. char outname[80];
  53. char header[134];            /* top of page header */
  54. char subheader[134];            /* sub title, */
  55.  
  56. /* Control characters are used to specify a character string; these
  57. perform various definable functions. The WS functions ^B, ^D, ^S, etc
  58. are done explicitly. */
  59.  
  60. #define CTLMAX 8            /* max size of string */
  61.  
  62. char ctlstr[32][CTLMAX + 1] = {        /* control character macros */
  63.     "",        /* NUL, not accessible */
  64.     "\033W0",    /* ESC W 0   Okidata double wide off */
  65.     "\033G",    /* ESC G     Okidata emphasized on */
  66.     "\033H",    /* ESC H     Okidata emphasized off */
  67.     "",        /* ^D */
  68.     "\033I\003",    /* ESC I ^C  Okidata CQ mode */
  69.     "\033I\001",    /* ESC I ^A  Okidata DP mode */
  70.     "\033W1",    /* ESC W 1   Okidata double wide on */
  71.  
  72.     "\010",        /* BS */
  73.     "\011",        /* HT */
  74.     "\012",        /* LF */
  75.     "",        /* ^K used by Index */
  76.     "\014",        /* FF */
  77.     "\015",        /* CR */
  78.     "\033%G",    /* ESC % G   Okidata italicized on */
  79.     "\033%H",    /* ESC % H   Okidata italicized off */
  80.  
  81.     "",        /* ^P used by Index */
  82.     "\0330",    /* ESC 0     Okidata 8 LPI */
  83.     "\033A\014\0332", /* ESC A ^L  ESC 2 Okidata 6 LPI */
  84.     "\033-\001",    /* ESC - ^A  Okidata underline on */
  85.     "\033-\200",    /* ESC - ^@ (null) underline off */
  86.     "\022",        /* NAK    Okidata 10CPI */
  87.     "\033:",    /* ESC :  Okidata 12CPI */
  88.     "\017",        /* ETB    Okidata 17.1CPI */
  89.  
  90.     "",
  91.     "",
  92.     "",
  93.     "",
  94.     "",
  95.     "",
  96.     "",
  97.     ""
  98. };
  99.  
  100. int graph_flag;                /* 1 == do output graphics */
  101.  
  102. #define MAXMEM 65535L            /* max we will allocate (note 64K - 1) */
  103. #define MINMEM (1024L * 3L)        /* the minimum */
  104.  
  105. long memsize;
  106.  
  107. char *inbuf;                /* input file buffer */
  108. unsigned ibufsize;            /* how big it is, */
  109. unsigned ibufcount;            /* how much is in it */
  110. unsigned ibufindex;
  111.  
  112. char *outbuf;                /* output buffer */
  113. unsigned obufsize;
  114. unsigned obufcount;
  115. unsigned obufindex;
  116.  
  117. char *auxbuf;
  118. unsigned abufsize;
  119. unsigned abufcount;
  120. unsigned abufindex;
  121.  
  122. static int _stack = 15000;
  123.  
  124. char *getmem();
  125. long sizmem();
  126.  
  127. /* Process the input file. If no output is specified, write it to
  128. the standard output. */
  129.  
  130. main(argc,argv)
  131. int argc;
  132. char *argv[];
  133. {
  134. char *p,arg[80],sw[80];
  135. int i,x;
  136. int have_file;
  137. int arg_error;
  138.  
  139.     printf ("TF - Text Formatter - (c) Fido Software  24 Oct 85\r\n");
  140.  
  141.     allmem();
  142.     memsize= sizmem();
  143.     if (memsize < MINMEM) {
  144.         printf("Go buy more memory.\r\n");
  145.         exit(1);
  146.     }
  147.     if (memsize > MAXMEM) memsize= MAXMEM;
  148.  
  149. /* Split the buffer into three pieces, input, aux input and output. */
  150.  
  151.     obufsize= 1024L;
  152.     ibufsize= abufsize= ((memsize - obufsize) / 2L);
  153.     outbuf= getmem( (int) memsize);
  154.     inbuf= &outbuf[obufsize];
  155.     auxbuf= &inbuf[ibufsize];
  156.  
  157.     ibufcount= ibufindex= 0;
  158.     obufcount= obufindex= 0;
  159.     abufcount= abufindex= 0;
  160.  
  161.     printf("Input Buffer    : %8d bytes\r\n",ibufsize);
  162.     printf(".IN File Buffer : %8d bytes\r\n",abufsize);
  163.     printf("Output Buffer   : %8d bytes\r\n",obufsize);
  164.  
  165.     newdelim(" \t\r\n;,");            /* arg delimiter list, */
  166.     pagelen= 66;                /* page length */
  167.     lmargin= 8;                /* left margin */
  168.     top_margin= 1;                /* top margin */
  169.     bot_margin= 8;                /* bottom margin */
  170.     *header= '\0';
  171.     *subheader= '\0';
  172.     num_pages= 1;                /* do auto page numbers */
  173.     graph_flag= 1;                /* do graphics */
  174.     have_file= 0;                /* no output file yet */
  175.     arg_error= 0;                /* no error yet, */
  176.     csource= 0;                /* not a C source, */
  177.     title= 0;                /* no title yet, */
  178.     lineno= 0;                /* no line numbers yet */
  179.     brackets= 0;
  180.     newpage= 0;
  181.     auxfile= 0;                /* not including */
  182.     first_page= 1;
  183.     num_pages= 10000;
  184.  
  185.     strcpy(inname,"");            /* no file yet, */
  186.     strcpy(outname,"prn");            /* default to printer */
  187.  
  188. /* Process the command line. We must have a filename, and optionally one
  189. of two options: list amount of memory, of add line numbers to the index. */
  190.  
  191.     x= 0;                    /* no filename yet */
  192.     while (--argc) {
  193.         ++argv;
  194.         cpyarg(arg,*argv);        /* possible name, */
  195.         if ((x == 0) && (strlen(arg) > 0)) { /* if no name yet, */
  196.             strcpy(inname,arg);    /* get one, */
  197.             x= 1;
  198.         }
  199.         strip_switch(sw,*argv);        /* get the switches, */
  200.         p= sw;
  201.  
  202.         while (*p) {
  203.             if (*p == 'L') {
  204.                 lineno= 1;
  205.                 printf(" - Line numbers\r\n");
  206.  
  207.             } else if (*p == 'U') {
  208.                 graph_flag= 0;
  209.                 printf(" - No output graphics\r\n");
  210.  
  211.             } else if (*p == 'C') {
  212.                 csource= 1;
  213.                 printf(" - C Source\r\n");
  214.  
  215.             } else if (*p == 'T') {
  216.                 title= 1;
  217.                 printf(" - Top of page Titles\r\n");
  218.  
  219.             } else if (*p == 'O') {
  220.                 strcpy(outname,arg);
  221.                 printf(" - Output to %s\r\n",outname);
  222.  
  223.             } else if (*p == 'P') {
  224.                 first_page= atoi(arg);
  225.                 if (first_page < 1) first_page= 1;
  226.                 printf("- Start Printing at Page #%u\r\n",first_page);
  227.  
  228.             } else if (*p == 'N') {
  229.                 num_pages= atoi(arg);
  230.                 if (num_pages < 1) num_pages= 1;
  231.                 printf("- Print Only %u Pages\r\n",num_pages);
  232.  
  233.             } else {
  234.                 printf("* I don't know what '%c' is\r\n",*p);
  235.                 ++arg_error;
  236.             }
  237.             ++p;
  238.         }
  239.     }
  240.  
  241.     if (*inname == '\0') {
  242.         printf("* Missing a File to Print!\r\n");
  243.         ++arg_error;
  244.  
  245.     } else {
  246.         infile= _xopen(inname,0);        /* open file, */
  247.         if (infile == -1) {
  248.             printf("\r\n* Can't find %s\r\n",inname);
  249.             ++arg_error;
  250.  
  251.         } else {
  252.             outfile= _xcreate(outname,2);
  253.             if (outfile == -1) {
  254.                 printf("\r\n* Can't write to %s\r\n",outname);
  255.                 ++arg_error;
  256.             }
  257.         }
  258.     }
  259.     if (arg_error) {
  260.         printf("\r\nTry: TF {switches} filename {outfile/O}    where\r\n");
  261.         printf("* filename is the file to print,\r\n");
  262.         printf("* outfile/O is where to print to (default is PRN)\r\n");
  263.         printf("* switches are: /C C source, /T Page titles, /L Line numbers\r\n");
  264.         printf("* x/P Start at page X, x/N Print X pages, /U no output graphics.\r\n");
  265.         exit(1);
  266.     }
  267.     if (csource) {
  268.         lmargin= 0;
  269.     }
  270.     print();
  271.  
  272.     while ((this_line > 0) && (this_line < pagelen))
  273.         lprintf("\r\n");        /* go to top of form */
  274.     wflush();
  275.     _xclose(infile); 
  276.     _xclose(outfile);
  277.     exit(0);                /* exit. */
  278. }
  279. /* Print each line to the printer, processing dot commands as we go. */
  280.  
  281. print()
  282. {
  283. char linebuf[132];        /* character line buffer */
  284. int i;
  285. char linenum[20];
  286. int last_page;
  287.  
  288.     line_count= 0;
  289.     this_page= abs_page= 1;
  290.     this_line= 0;
  291.     this_col= 0;
  292.     newpage= 0;
  293.     last_page= -1;
  294.  
  295.     while (fill_line(linebuf,sizeof(linebuf))) {
  296.  
  297.         if (last_page != this_page) {    /* local display */
  298.             printf("At Page #%-4u",this_page);
  299.             if (abs_page != this_page) printf(" (%d)",abs_page);
  300.             printf("\r");
  301.             last_page= this_page;
  302.         }
  303.  
  304.         if (scan_line(linebuf) == TRUE)    /* look for dot cmds */
  305.             continue;
  306.  
  307.         if (this_page >= first_page + num_pages)
  308.             return;            /* quit if last page */
  309.  
  310.         ++line_count;            /* count total lines,*/
  311.         if (this_line == 0) {
  312.             do_header();        /* do headers, */
  313.             i= top_margin;
  314.             while (i--) {        /* do top margin, */
  315.                 lprintf("\r\n");
  316.             }
  317.         }
  318.  
  319. /* If a non blank line, do the left margin, line numbers, etc and print
  320. the text. If a blank line, just do a line feed, for speed. */
  321.  
  322.         if (strlen(linebuf) > 0) {
  323.             for (i= lmargin; i--;)
  324.                 lputc(' ');
  325.             if (lineno) {
  326.                 lprintf("%4u: ",line_count + 1);
  327.                 this_col-= strlen(linenum);
  328.             }
  329.             lprintf("%s\r\n",linebuf);
  330.  
  331.         } else lprintf("\r\n");
  332.  
  333. /* If at the bottom of the page, go to the next line. This is either
  334. beyond the edge of the paper, or a C source and the bracket count went
  335. to zero. */
  336.         if ((pagelen > 0) && (this_line > (pagelen - bot_margin)) || (newpage && csource)) {
  337.             while (this_line < pagelen)
  338.                 lprintf("\r\n");
  339.             ++this_page;
  340.             ++abs_page;
  341.             this_line= 0;
  342.             newpage= 0;
  343.         }
  344.     }
  345. }
  346. /* Compare two strings, of a given length. Check only for equality. Return
  347. 0 if equal, else 1. */
  348.  
  349. compl(length,first,last)
  350. int length;
  351. char *first,*last;
  352. {
  353.  
  354.     for (; length > 0; length--)
  355.     {    if (  (toupper(*first)) != (toupper(*last))  )
  356.             return (1);
  357.         ++first; ++last;
  358.     }
  359.     return (0);
  360. }
  361. /* Fill a line buffer with characters. Return null if end of file. */
  362.  
  363. fill_line(line,len)
  364. char *line;
  365. int len;
  366. {
  367. char d;
  368.  
  369.     while (len > 0) {
  370.         d= getmc() & 0x7f;        /* get a char from the file */
  371.         if (d == CR) continue;
  372.         if (d == LF) break;
  373.         if (d == '\0') break;
  374.  
  375.         if (d == '{') ++brackets;
  376.         if (d == '}') if (--brackets == 0) newpage= 1;
  377.         *line++= d;
  378.         --len;
  379.     }
  380.     *line= '\0';
  381.     return(d);
  382. }
  383. /* Fill the memory buffer with characters from the file, or the
  384. aux file (.in file) if open. Returns NUL when the file is empty. This
  385. throws away nulls and control-Zs. */
  386.  
  387. getmc() {
  388.  
  389. char c;
  390.  
  391.     while (1) {
  392.         if (auxfile != 0) {        /* if aux file read from that */
  393.             if (abufindex >= abufcount) {
  394.                 abufindex= 0;
  395.                 abufcount= _xread(auxfile,auxbuf,abufsize);
  396.                 if (abufcount == 0) {
  397.                     _xclose(auxfile);
  398.                     auxfile= 0;
  399.                     continue;
  400.                 }
  401.             }
  402.             c= auxbuf[abufindex++];
  403.             if ((c == NUL) || (c == SUB)) continue;
  404.             return(c);
  405.         } 
  406.         if (ibufindex >= ibufcount) {
  407.             ibufindex= 0;
  408.             ibufcount= _xread(infile,inbuf,ibufsize);
  409.             if (ibufcount == 0) return(NUL);
  410.         }
  411.         c= inbuf[ibufindex++];
  412.         if ((c == SUB) || (c == NUL)) continue;
  413.         return(c);
  414.     }
  415. }
  416.  
  417. /* Scan for dot commands. When and if we find a dot command, fool the 
  418. caller into thinking that the line we were passed is now empty. (Return TRUE)
  419. If we find a formfeed, treat it the same as a .pa. */
  420.  
  421. scan_line(s)
  422. char *s;
  423. {
  424. int n,i;
  425. char c;
  426.  
  427.     if (*s =='.') {                 /* must be first atom */
  428.         if (compl (3,s,".pa") == 0) {
  429.             while ((pagelen > 0) && (this_line < pagelen)) {
  430.                 lprintf("\r\n");
  431.             }
  432.             ++this_page;
  433.             ++abs_page;
  434.             this_line= 0;
  435.  
  436.         } else if (compl(3,s,".def") == 0) {        /* define control char */
  437.             s= next_arg(s);
  438.             n= atoi(s);
  439.             if ((n > 0) && (n < 32)) {                /* if one there, */
  440.                 for (i= 0; i < CTLMAX; i++) {
  441.                     s= next_arg(s);        /* insert chars until */
  442.                     if (! *s) break;    /* end of string */
  443.                     ctlstr[n][i]= atoi(s);
  444.                 }
  445.                 ctlstr[n][i]= '\0';        /* terminate */
  446.             }
  447.  
  448.         } else if (compl (3,s,".im") == 0) {        /* binary image file */
  449.             rawfile(next_arg(s));
  450.  
  451.         } else if (compl (3,s,".in") == 0) {
  452.             if (auxfile == 0) {            /* if one not open */
  453.                 cpyarg(auxname,next_arg(s));    /* get clean filename */
  454.                 auxfile= _xopen(auxname,0);    /* open it, */
  455.                 abufcount= 0;
  456.                 abufindex= 0;
  457.                 if (auxfile == -1) {
  458.                     auxfile= 0;    /* cant open */
  459.                     cprintf("\07\r\n* Cant find .in file '%s'\r\n",auxname);
  460.                 }
  461.  
  462.             } else cprintf("\07\r\n* Cant nest .in files: %s from within %s\r\n",
  463.                 next_arg(s),auxname);
  464.  
  465.  
  466.         } else if (compl (3,s,".pn") == 0) {
  467.             i= atoi(next_arg(s));        /* get page num */
  468.             if (i > 0) this_page= i;    /* set if reasonable */
  469.  
  470.         } else if (compl (3,s,".pl") == 0) {
  471.             pagelen= atoi(next_arg(s));
  472.  
  473.         } else if (compl (3,s,".mt") == 0) {
  474.             i= atoi(next_arg(s));
  475.             if ((i > 0) && (i < 40))    /* get top margin, */
  476.                 top_margin= i;        /* set if reasonable */
  477.  
  478.         } else if (compl (3,s,".mb") == 0) {
  479.             i= atoi(next_arg(s));
  480.             if (i < pagelen)        /* set bottom margin */
  481.                 bot_margin= i;
  482.  
  483.         } else if (compl (3,s,".ti") == 0) {
  484.             title= 1;
  485.  
  486.         } else if (compl (3,s,".he") == 0) {
  487.             strcpy(header,next_arg(s));
  488.  
  489.         } else if (compl (3,s,".sh") == 0) {
  490.             strcpy(subheader,next_arg(s));
  491.  
  492.         } else if (compl (3,s,".lm") == 0) {
  493.                 i= atoi(next_arg(s));
  494.                 if (i <80) lmargin= i;
  495.         }
  496.         return (TRUE);
  497.  
  498.     } else if (*s == FF) {
  499.         if (this_page >= first_page) lputc(FF);
  500.         ++this_page;
  501.         ++abs_page;
  502.         this_line= 0;
  503.         return(TRUE);
  504.     }
  505.     return (FALSE);
  506. }
  507. /* Send a raw file to the printer. The first line should contain a number
  508. specifying the number of lines it occupies. */
  509.  
  510. rawfile(t)
  511. char *t;
  512. {
  513. int i,f;
  514. char ln[80];
  515.  
  516.     f= _xopen(t,0);
  517.     if (f != -1) {
  518.         wflush();            /* keep in sync */
  519.  
  520.         _xline(f,ln,sizeof(ln));
  521.         this_line += atoi(ln);        /* just assume ... */
  522.  
  523.         while (i= _xread(f,ln,sizeof(ln))) {
  524.             _xwrite(outfile,ln,i);
  525.         }
  526.         _xclose(f);
  527.     }
  528. }
  529. /* Print the top of page header. If we find a #, replace it with 
  530. the current page number. */
  531.  
  532. do_header() {
  533.  
  534. char c;
  535. char *p;
  536. char pnum[82];
  537. char date[20];
  538. int i;
  539.  
  540.     if (title) {
  541.         gtod(date);
  542.         lprintf("%-12s -- %9s %s %9s Page %d\r\n",
  543.             inname," ",date," ",this_page);
  544.     }
  545.     if (*header) hdrtxt(header);
  546.     if (*subheader) hdrtxt(subheader);
  547.  
  548. }
  549. /* Print the header text, expanding line number (#) with left margins. */
  550.  
  551.  
  552. hdrtxt(p)
  553. char *p;
  554. {
  555. int i;
  556.  
  557.     for (i= lmargin; i--;) lputc(' ');
  558.  
  559.     while (*p) {
  560.         if (*p == '#') lprintf("%d",this_page);
  561.         else lputc(*p);
  562.         ++p;
  563.     }
  564.     lprintf("\r\n");
  565. }
  566. /* Print to the output file. */
  567.  
  568. lprintf(f)
  569. char *f;
  570. {
  571. char buf[500],*p;
  572.  
  573.     _spr(buf,&f);
  574.     p= buf;
  575.     while (*p) lputc(*p++);
  576. }
  577.  
  578. /* Write a character to the output file. This is the highest level of
  579. character output; it does bold, underline, etc, as well as counting lines
  580. and columns.
  581.  Write a character to the file. Count LF's as lines as they go by. Control
  582. characters are defined by the switch() to do the normal ASCII function, but
  583. what is actually output depends on the control character translation table. */
  584.  
  585. lputc(c)
  586. char c;
  587. {
  588. char b;
  589. int i;
  590.  
  591.     if (c < ' ') { 
  592.         switch(c) {
  593.             case TAB: do lputc(' '); while (this_col % 8);
  594.                 c= '\0'; break;
  595.  
  596.             case LF: ++this_line;
  597.             case CR: case FF: this_col= 0; break;
  598.  
  599.             case BS: --this_col; break;
  600.  
  601.         }
  602.         for (i= 0; ctlstr[c][i]; i++) {    /* control char macros */
  603.             b= ctlstr[c][i];    /* convert 80h to NUL */
  604.             if (b == '\200') b= '\0';
  605.             lputc3(b);
  606.         }
  607.  
  608.     } else {
  609.         ++this_col;        /* printable only */
  610.         lputc3(c);
  611.     }
  612. }
  613.  
  614. /* Lowest level of character IO. */
  615.  
  616. lputc3(c)
  617. char c;
  618. {
  619.     if (this_page < first_page) return;
  620.  
  621.     outbuf[obufindex++]= c;
  622.     if (obufindex >= obufsize) wflush();
  623. }
  624.  
  625. /* Flush the output buffer. */
  626.  
  627. wflush() {
  628.  
  629.     if (obufindex > 0) {
  630.         if (_xwrite(outfile,outbuf,obufindex) != obufindex) {
  631.             printf("\r\n* \07Disk Full!\r\n");
  632.             _close(outfile);
  633.             exit(1);
  634.         }
  635.         obufindex= 0;
  636.     }
  637. }
  638.